package com.njcb.ams.bootconfig;

import com.njcb.ams.support.config.AmsCacheConfiguration;
import com.njcb.ams.support.config.AmsConfigUtil;
import com.njcb.ams.support.config.defaultconfig.AmsDefaultCacheConfig;
import net.sf.ehcache.Cache;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.CacheConfiguration.CacheEventListenerFactoryConfiguration;
import net.sf.ehcache.config.PersistenceConfiguration;
import net.sf.ehcache.config.PersistenceConfiguration.Strategy;
import net.sf.ehcache.distribution.CacheManagerPeerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.util.ArrayList;
import java.util.List;

/**
 * 用于构建缓存ehcache
 * @author liuyanlong
 *
 */
@Configuration
@EnableCaching
public class SpringCacheConfig {

	@Autowired
	private AmsProperties amsProperties;

	/**
	 * ehcache 主要的管理器
	 * @return 缓存管理器
	 */
	@Bean(name = "cacheManager")
	public CacheManager cacheManager() {
		EhCacheManagerFactoryBean bean = ehCacheManager();
		net.sf.ehcache.CacheManager cacheManager = bean.getObject();
		cacheConfig(cacheManager);
		return new EhCacheCacheManager(cacheManager);
	}

	/**
	 * 据shared与否的设置, Spring分别通过CacheManager.create() 或new
	 * CacheManager()方式来创建一个ehcache基地.
	 * 也说是说通过这个来设置cache的基地是这里的Spring独用,还是跟别的(如hibernate的Ehcache共享)
	 * @return 缓存管理器工厂
	 */
	@Bean(name = "ehcacheManager")
	public EhCacheManagerFactoryBean ehCacheManager() {
		EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();
		cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ams-ehcache.xml"));
		cacheManagerFactoryBean.setShared(false);
		return cacheManagerFactoryBean;
	}
	
	/**
	 * 集群同步
	 * @return
	 */
	private CacheConfiguration defaultCacheConfiguration(String name){
		return getCacheConfiguration(name);
	}

	private CacheConfiguration getCacheConfiguration(String name) {
		CacheConfiguration cacheConfiguration = new CacheConfiguration();
		cacheConfiguration.setMaxEntriesLocalHeap(100000);
		cacheConfiguration.setEternal(false);
		cacheConfiguration.setTimeToIdleSeconds(86400);
		cacheConfiguration.setTimeToLiveSeconds(0);
		CacheEventListenerFactoryConfiguration factory = new CacheEventListenerFactoryConfiguration();
		factory.className("net.sf.ehcache.distribution.RMICacheReplicatorFactory");
		cacheConfiguration.cacheEventListenerFactory(factory);
		cacheConfiguration.setName(name);
		PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration();
		persistenceConfiguration.strategy(Strategy.LOCALTEMPSWAP);
		cacheConfiguration.persistence(persistenceConfiguration);
		return cacheConfiguration;
	}

	/**
	 * 单机缓存
	 * @return
	 */
	private CacheConfiguration aloneCacheConfiguration(String name){
		return getCacheConfiguration(name);
	}
	
	/**
	 * 缓存配置
	 * @param cacheManager
	 */
	private void cacheConfig(net.sf.ehcache.CacheManager cacheManager){
		AmsCacheConfiguration cacheConfiguration = AmsConfigUtil.getBean(AmsCacheConfiguration.class);
		if(null == cacheConfiguration){
			cacheConfiguration = new AmsDefaultCacheConfig();
		}
		List<String> peerList = new ArrayList<String>();
		cacheConfiguration.registerPeer(peerList);
		StringBuilder peerSb = new StringBuilder();
		for (String peer : peerList) {
			peerSb.append(peer + "|");
		}
		if(peerSb.length() > 0){
			peerSb.deleteCharAt(peerSb.length()-1);
		}
		CacheManagerPeerProvider pro = cacheManager.getCacheManagerPeerProviders().get("RMI");
		if(null != pro){
			pro.registerPeer(peerSb.toString());
		}
		
		List<Cache> cacheList = new ArrayList<Cache>();
		cacheConfiguration.addEhCache(cacheList);
		cacheList.add(new Cache(defaultCacheConfiguration("SysParamCache")));
		cacheList.add(new Cache(defaultCacheConfiguration("UserTempParamCache")));
		cacheList.add(new Cache(defaultCacheConfiguration("UserDynamicCache")));
		cacheList.add(new Cache(aloneCacheConfiguration("userStaticCacheCache")));
		for (Cache cache : cacheList) {
			cacheManager.addCache(cache);
		}
	}

}
